import functools
import logging
import traceback
from datetime import datetime
from flask import request, jsonify, current_app, g
from flask_jwt_extended import get_jwt_identity, verify_jwt_in_request
from sqlalchemy.exc import SQLAlchemyError
from app.extensions import db
from app.models.user import User


def handle_errors(f):
    """
    统一错误处理装饰器
    """
    @functools.wraps(f)
    def decorated_function(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except ValueError as e:
            current_app.logger.warning(f'参数错误: {str(e)}')
            return jsonify({'error': str(e)}), 400
        except PermissionError as e:
            current_app.logger.warning(f'权限错误: {str(e)}')
            return jsonify({'error': '权限不足'}), 403
        except FileNotFoundError as e:
            current_app.logger.warning(f'资源不存在: {str(e)}')
            return jsonify({'error': '资源不存在'}), 404
        except SQLAlchemyError as e:
            current_app.logger.error(f'数据库错误: {str(e)}')
            db.session.rollback()
            return jsonify({'error': '数据库操作失败'}), 500
        except Exception as e:
            current_app.logger.error(f'未知错误: {str(e)}\n{traceback.format_exc()}')
            return jsonify({'error': '服务器内部错误'}), 500
    
    return decorated_function


def log_api_call(f):
    """
    API调用日志装饰器
    """
    @functools.wraps(f)
    def decorated_function(*args, **kwargs):
        start_time = datetime.utcnow()
        
        # 记录请求信息
        request_info = {
            'method': request.method,
            'url': request.url,
            'endpoint': request.endpoint,
            'remote_addr': request.remote_addr,
            'user_agent': request.headers.get('User-Agent', ''),
            'content_type': request.content_type
        }
        
        # 获取用户ID（如果已认证）
        user_id = None
        try:
            verify_jwt_in_request(optional=True)
            user_id = get_jwt_identity()
        except:
            pass
        
        current_app.logger.info(f'API调用开始: {request_info}')
        
        try:
            # 执行原函数
            result = f(*args, **kwargs)
            
            # 计算执行时间
            end_time = datetime.utcnow()
            duration = (end_time - start_time).total_seconds()
            
            # 记录成功日志
            current_app.logger.info(
                f'API调用成功: {request.endpoint} - 用户ID: {user_id} - 耗时: {duration:.3f}s'
            )
            
            return result
            
        except Exception as e:
            # 计算执行时间
            end_time = datetime.utcnow()
            duration = (end_time - start_time).total_seconds()
            
            # 记录错误日志
            current_app.logger.error(
                f'API调用失败: {request.endpoint} - 用户ID: {user_id} - 耗时: {duration:.3f}s - 错误: {str(e)}'
            )
            
            raise
    
    return decorated_function


def require_permissions(*permissions):
    """
    权限检查装饰器
    """
    def decorator(f):
        @functools.wraps(f)
        def decorated_function(*args, **kwargs):
            try:
                verify_jwt_in_request()
                current_user_id = get_jwt_identity()
                
                if not current_user_id:
                    raise PermissionError('用户未认证')
                
                # 获取当前用户
                user = User.query.get(current_user_id)
                if not user:
                    raise PermissionError('用户不存在')
                
                # 检查用户权限（这里可以根据实际需求扩展权限系统）
                # 目前简化处理，所有认证用户都有基本权限
                user_permissions = ['basic']  # 可以从数据库或配置中获取
                
                # 检查是否有所需权限
                for permission in permissions:
                    if permission not in user_permissions:
                        raise PermissionError(f'缺少权限: {permission}')
                
                # 将用户信息存储到g对象中，供后续使用
                g.current_user = user
                
                return f(*args, **kwargs)
                
            except Exception as e:
                current_app.logger.warning(f'权限检查失败: {str(e)}')
                raise
        
        return decorated_function
    return decorator


def rate_limit(max_requests=100, window_seconds=3600):
    """
    简单的速率限制装饰器
    """
    def decorator(f):
        @functools.wraps(f)
        def decorated_function(*args, **kwargs):
            # 这里可以实现基于Redis的速率限制
            # 目前简化处理，仅记录日志
            current_app.logger.debug(f'速率限制检查: {request.remote_addr}')
            return f(*args, **kwargs)
        
        return decorated_function
    return decorator


def validate_json_input(required_fields=None, optional_fields=None):
    """
    JSON输入验证装饰器
    """
    def decorator(f):
        @functools.wraps(f)
        def decorated_function(*args, **kwargs):
            if not request.is_json:
                raise ValueError('请求必须是JSON格式')
            
            data = request.get_json()
            if not data:
                raise ValueError('请求体不能为空')
            
            # 检查必需字段
            if required_fields:
                missing_fields = []
                for field in required_fields:
                    if field not in data or data[field] is None:
                        missing_fields.append(field)
                
                if missing_fields:
                    raise ValueError(f'缺少必需字段: {", ".join(missing_fields)}')
            
            # 检查字段类型（可以根据需要扩展）
            # 这里简化处理，仅检查字段存在性
            
            return f(*args, **kwargs)
        
        return decorated_function
    return decorator


def cache_result(timeout=300):
    """
    结果缓存装饰器（简化版）
    """
    def decorator(f):
        @functools.wraps(f)
        def decorated_function(*args, **kwargs):
            # 这里可以实现基于Redis的缓存
            # 目前直接执行函数
            return f(*args, **kwargs)
        
        return decorated_function
    return decorator


class APILogger:
    """
    API日志记录器
    """
    
    @staticmethod
    def log_user_action(user_id: int, action: str, details: dict = None):
        """记录用户操作日志"""
        log_data = {
            'user_id': user_id,
            'action': action,
            'details': details or {},
            'ip_address': request.remote_addr,
            'user_agent': request.headers.get('User-Agent', ''),
            'timestamp': datetime.utcnow().isoformat()
        }
        
        current_app.logger.info(f'用户操作: {log_data}')
    
    @staticmethod
    def log_device_event(device_id: str, event: str, user_id: int = None, data: dict = None):
        """记录设备事件日志"""
        log_data = {
            'device_id': device_id,
            'event': event,
            'user_id': user_id,
            'data': data or {},
            'timestamp': datetime.utcnow().isoformat()
        }
        
        current_app.logger.info(f'设备事件: {log_data}')
    
    @staticmethod
    def log_treatment_event(treatment_id: int, event: str, user_id: int, data: dict = None):
        """记录治疗事件日志"""
        log_data = {
            'treatment_id': treatment_id,
            'event': event,
            'user_id': user_id,
            'data': data or {},
            'timestamp': datetime.utcnow().isoformat()
        }
        
        current_app.logger.info(f'治疗事件: {log_data}')
    
    @staticmethod
    def log_security_event(event: str, user_id: int = None, details: dict = None):
        """记录安全事件日志"""
        log_data = {
            'event': event,
            'user_id': user_id,
            'details': details or {},
            'ip_address': request.remote_addr,
            'user_agent': request.headers.get('User-Agent', ''),
            'timestamp': datetime.utcnow().isoformat()
        }
        
        current_app.logger.warning(f'安全事件: {log_data}')


def log_user_action(action: str, details: dict = None):
    """
    用户操作日志装饰器
    """
    def decorator(f):
        @functools.wraps(f)
        def decorated_function(*args, **kwargs):
            try:
                # 执行原函数
                result = f(*args, **kwargs)
                
                # 记录成功的用户操作
                try:
                    user_id = get_jwt_identity()
                    if user_id:
                        APILogger.log_user_action(user_id, action, details)
                except:
                    pass  # 忽略日志记录错误
                
                return result
                
            except Exception as e:
                # 记录失败的用户操作
                try:
                    user_id = get_jwt_identity()
                    if user_id:
                        error_details = details.copy() if details else {}
                        error_details['error'] = str(e)
                        APILogger.log_user_action(user_id, f'{action}_failed', error_details)
                except:
                    pass  # 忽略日志记录错误
                
                raise
        
        return decorated_function
    return decorator


# 使用示例装饰器组合
def api_endpoint(permissions=None, log_action=None, required_fields=None):
    """
    组合装饰器，用于API端点
    """
    def decorator(f):
        # 应用多个装饰器
        decorated = f
        
        # 错误处理（最外层）
        decorated = handle_errors(decorated)
        
        # API调用日志
        decorated = log_api_call(decorated)
        
        # 用户操作日志
        if log_action:
            decorated = log_user_action(log_action)(decorated)
        
        # 权限检查
        if permissions:
            decorated = require_permissions(*permissions)(decorated)
        
        # JSON输入验证
        if required_fields:
            decorated = validate_json_input(required_fields)(decorated)
        
        return decorated
    
    return decorator